/*
** DEFINITIONS SECTION
*/

%token PROGRAM
%token PROCEDURE
%token FUNCTION
%token CONST 
%token TYPE 
%token VAR 
%token ARRAY 
%token BOOLEAN 
%token CHAR 
%token INTEGER
%token REAL 
%token RECORD 
%token BEGIN_ 
%token END 
%token OF 
%token IF 
%token THEN 
%token ELSE 
%token FOR 
%token TO 
%token DOWNTO 
%token DO 
%token NEW 
%token DISPOSE	
%token VIRGULA
%token PONTO_E_VIRGULA 
%token DOIS_PONTOS
%token PONTO 
%token OPERADOR_DE_ATRIBUICAO
%token OPERADOR_DE_SUBFAIXA
%token SOMA 
%token SUBTRACAO
%token ASTERISCO
%token DIVISAO
%token ENDERECO
%token VALOR_DE_PONTEIRO
%token MOD	
%token AND 
%token OR 
%token NOT 
%token IGUALDADE
%token DESIGUALDADE
%token MENOR 
%token MENOR_OU_IGUAL
%token MAIOR 
%token MAIOR_OU_IGUAL
%token ABRE_PARENTESIS 
%token FECHA_PARENTESIS
%token ABRE_COLCHETE
%token FECHA_COLCHETE
%token CONDICIONAL_TERNARIO
%token VALOR 
%token IDENTIFICADOR
%token FIM_DE_ARQUIVO	
%token ARROBA
%token WHILE
%token BREAK
%token GOTO
%token READ
%token PRINT
%token REPEAT
%token UNTIL
%token STEP

%start program

%left NOT
%left AND ASTERISCO DIVISAO   
%left SOMA SUBTRACAO MOD OR CONDICIONAL_TERNARIO
%left IGUALDADE DESIGUALDADE MENOR MENOR_OU_IGUAL MAIOR MAIOR_OU_IGUAL

/*
** RULES SECTION
*/

%%

program: PROGRAM IDENTIFICADOR PONTO_E_VIRGULA declarations sub_programs block PONTO;

declarations: CONST const_declaration
			| TYPE type_declaration
			| VAR var_declaration
			|
			;

sub_programs: function_declaration sub_programs
			| procedure_declaration sub_programs
			|
			;

const_declaration:	IDENTIFICADOR OPERADOR_DE_ATRIBUICAO VALOR PONTO_E_VIRGULA const_declaration
				 |	
				 ;

type_declaration: IDENTIFICADOR DOIS_PONTOS type PONTO_E_VIRGULA type_declaration
				| 
				;

var_declaration: id_list DOIS_PONTOS type PONTO_E_VIRGULA var_declaration
			   |
		       ;

id_list: id_list VIRGULA IDENTIFICADOR
	   | IDENTIFICADOR
	   ;

function_declaration: FUNCTION IDENTIFICADOR ABRE_PARENTESIS parameters FECHA_PARENTESIS DOIS_PONTOS type PONTO_E_VIRGULA declarations block PONTO_E_VIRGULA;

procedure_declaration: PROCEDURE IDENTIFICADOR ABRE_PARENTESIS parameters FECHA_PARENTESIS PONTO_E_VIRGULA declarations block PONTO_E_VIRGULA;
	
parameters: parameters PONTO_E_VIRGULA id_list DOIS_PONTOS type
		  | id_list DOIS_PONTOS type
		  ;

type: INTEGER
    | BOOLEAN
    | REAL
    | CHAR
    | array
    | enum
    | record
    | range
    ;

array:	ARRAY range OF type
	 ;

enum: ABRE_PARENTESIS subrange FECHA_PARENTESIS
	;

range: ABRE_COLCHETE list_subrange FECHA_COLCHETE
	 ;

list_subrange: list_subrange VIRGULA subrange
			 | subrange
			 ;

subrange: regra_x OPERADOR_DE_SUBFAIXA regra_x
		;

regra_x: access
	   | VALOR
	   ;

record: RECORD id_list DOIS_PONTOS type END
	  ;

block: BEGIN_ statements END
	 ;

statements: statement PONTO_E_VIRGULA statements
		  |
		  ;

statement: block
		 | expression
		 | control
		 | BREAK
		 | access OPERADOR_DE_ATRIBUICAO expression
		 ;

access: IDENTIFICADOR
	  | access ABRE_COLCHETE expression FECHA_COLCHETE
	  | access PONTO IDENTIFICADOR
	  ;


expression: expression operator factor
		  | expression2 CONDICIONAL_TERNARIO expression DOIS_PONTOS expression
	  	  | factor
		  ;

expression2: expression2 operator factor
	  	  | factor
		  ;

operator: SOMA
		| SUBTRACAO
		| MENOR
		| MAIOR
		| MENOR_OU_IGUAL
		| MAIOR_OU_IGUAL
		| IGUALDADE
		| DESIGUALDADE
		| ASTERISCO
		| DIVISAO
		| AND
		| OR
		;

factor: access
	  | NOT expression
	  | SOMA expression
	  | SUBTRACAO expression
	  | ABRE_PARENTESIS expression FECHA_PARENTESIS
	  | VALOR
	  ;

control: IF expression THEN statements 
	   | IF expression THEN statements  ELSE statements 
	   | WHILE expression DO statements 
	   | REPEAT statements UNTIL expression 
	   | FOR expression TO expression STEP expression DO block 
	   ;

%%

/*
** CODE SECTION
*/
#include "lex.yy.c"


int yyerror(char *message) {
	mensagemErro(message, lc);
	return 1;
}

int main(int argc, char** argv) {
	yyin = fopen(argv[1], "r");
	yyparse( );
	mostrarMensagens( );
	return EXIT_SUCCESS;
}


